// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.assets.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.assets.dto.ImportAssetsExpenseDto;
import com.liuxinlong.modules.assets.service.AssetsExpenseService;
import com.liuxinlong.modules.dao.AssetsDepartmentDao;
import com.liuxinlong.modules.dao.AssetsExpenseDao;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.entity.ExpenseOrder;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 费用维护管理业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2024-01-09
 */
@Service
@Slf4j
public class AssetsExpenseServiceImpl implements AssetsExpenseService {

    @Autowired
    private AssetsExpenseDao assetsExpenseDao;

    @Autowired
    private AssetsDepartmentDao assetsDepartmentDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Override
    @Transactional
    public List<Map<String, Object>> pageAssetsExpenseInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<ExpenseOrder> originalList = assetsExpenseDao.pageAssetsExpenseInfo(queryParam);
        List<Map<String, Object>> resultList = completeResult(originalList, startNum);
        return resultList;
    }

    @Override
    public int getAssetsExpenseInfoCount(Map<String, Object> queryParam) {
        return assetsExpenseDao.getAssetsExpenseInfoCount(queryParam);
    }

    @Override
    @Transactional
    public void addAssetsExpenseInfo(ExpenseOrder expenseOrder) {
        String id = SnowFlake.nextIdStr();
        expenseOrder.setId(id);
        expenseOrder.setYear(expenseOrder.getYear().substring(0,4));
        expenseOrder.setMonth(expenseOrder.getMonth().substring(5,7));
        if (StringUtils.equals(expenseOrder.getAccountBook(),"2110") || StringUtils.equals(expenseOrder.getAccountBook(),"2220")) {
            expenseOrder.setDomain("WPC");
        } else if(StringUtils.equals(expenseOrder.getAccountBook(),"3110") || StringUtils.equals(expenseOrder.getAccountBook(),"3220")) {
            expenseOrder.setDomain("CEP");
        } else {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"新增失败，账套非法！");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        expenseOrder.setCreateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        expenseOrder.setCreateTime(currentTime);
        assetsExpenseDao.insert(expenseOrder);
    }

    @Override
    @Transactional
    public void updateAssetsExpenseInfo(ExpenseOrder expenseOrder) {
        String id = expenseOrder.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改费用订单信息失败，费用订单信息不存在！");
        }
        if (StringUtils.equals(expenseOrder.getAccountBook(),"2110") || StringUtils.equals(expenseOrder.getAccountBook(),"2220")) {
            expenseOrder.setDomain("WPC");
        } else if(StringUtils.equals(expenseOrder.getAccountBook(),"3110") || StringUtils.equals(expenseOrder.getAccountBook(),"3220")) {
            expenseOrder.setDomain("CEP");
        } else {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"修改失败，账套非法！");
        }
        ExpenseOrder oldInfo = assetsExpenseDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改费用订单信息失败，费用订单信息不存在！");
        }
        expenseOrder.setYear(expenseOrder.getYear().substring(0,4));
        expenseOrder.setMonth(expenseOrder.getMonth().substring(5,7));
        expenseOrder.setCreateTime(oldInfo.getCreateTime());
        expenseOrder.setCreateUser(oldInfo.getCreateUser());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        expenseOrder.setUpdateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        expenseOrder.setUpdateTime(currentTime);
        assetsExpenseDao.updateById(expenseOrder);
    }

    @Override
    @Transactional
    public void deleteAssetsExpenseInfo(String id) {
        ExpenseOrder assetsExpense = assetsExpenseDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsExpense)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，费用订单信息不存在！");
        }
        assetsExpenseDao.deleteById(id);
    }

    @Override
    public void exportAssetsExpense(Map<String, Object> queryParam, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("固资费用订单导出excel.xlsx");
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<ExpenseOrder> assetsExpenseList = assetsExpenseDao.pageAssetsExpenseInfo(queryParam);
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        String[] head = {"序号", "账套", "年度", "月份", "凭证描述", "科目号", "品类", "部门", "项目号", "金额", "摘要"};
        data.setHead(head);
        String[][] dataList = new String[assetsExpenseList.size()][head.length];
        int index = 0;
        for (ExpenseOrder assetsExpense : assetsExpenseList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = assetsExpense.getAccountBook();
            dataList[index][2] = assetsExpense.getYear();
            dataList[index][3] = assetsExpense.getMonth();
            dataList[index][4] = assetsExpense.getDesc();
            dataList[index][5] = assetsExpense.getAccountNumber();
            dataList[index][6] = assetsExpense.getProductType();
            dataList[index][7] = departmentMap.get(assetsExpense.getDepartment()).get("name");
            dataList[index][8] = assetsExpense.getProjectNo();
            dataList[index][9] = String.valueOf(assetsExpense.getAmount());
            dataList[index][10] = assetsExpense.getBrief();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public ImportResp importAssetsExpense(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                ExpenseOrder expenseOrder = covertToBean(record);
                return false;
//				try {
//					materialStandardDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetCode(ReturnCodes.HTTP_SUCCESS.getRetCode());
                resp.setRetMessage("导入费用订单数据部分失败，总数=" + resp.getTotal() + ",失败总数=" +
                        resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入费用订单数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("accountBook", failRecord[0].trim());
                    item.put("year", failRecord[1]);
                    item.put("month", failRecord[2]);
                    item.put("desc", failRecord[3]);
                    item.put("accountNumber", failRecord[4]);
                    item.put("productType", failRecord[5]);
                    item.put("department", failRecord[6].toUpperCase());
                    item.put("projectNo", failRecord[7]);
                    item.put("amount", failRecord[8]);
                    item.put("brief", failRecord[9]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddAssetsExpense(List<ImportAssetsExpenseDto> dataList) {
        Map<String, Map<String, String>> departmentSnMap = assetsDepartmentDao.getAssetsDepartmentMapBySn();
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        List<Map> failedList = new ArrayList<>();
        boolean insertSuccess;
        int sort = 1;
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<ExpenseOrder> expenseOrderList = new ArrayList<>();
        for (ImportAssetsExpenseDto expenseDto : dataList) {
            ExpenseOrder expenseOrder = new ExpenseOrder();
            String accountBook = expenseDto.getAccountBook();
            if (StringUtils.equals(accountBook,"2110") || StringUtils.equals(accountBook,"2220")) {
                expenseOrder.setDomain("WPC");
            } else if(StringUtils.equals(accountBook,"3110") || StringUtils.equals(accountBook,"3220")) {
                expenseOrder.setDomain("CEP");
            } else {
                Map item = ObjectUtils.object2Map(expenseDto);
                item.put("message", "账套非法！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            expenseOrder.setAccountBook(expenseDto.getAccountBook());
            expenseOrder.setYear(expenseDto.getYear());
            expenseOrder.setMonth(expenseDto.getMonth());
            expenseOrder.setDesc(expenseDto.getDesc());
            expenseOrder.setAccountNumber(expenseDto.getAccountNumber());
            expenseOrder.setProductType(expenseDto.getProductType());
            String departmentSn = expenseDto.getDepartment().toUpperCase();
            if (!departmentSnMap.containsKey(departmentSn)) {
                Map item = ObjectUtils.object2Map(expenseDto);
                item.put("message", "部门不存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            expenseOrder.setDepartment(departmentSnMap.get(departmentSn).get("department"));
            expenseOrder.setProjectNo(expenseDto.getProjectNo());
            expenseOrder.setAmount(expenseDto.getAmount());
            expenseOrder.setBrief(expenseDto.getBrief());

            String message = "";
            String id = SnowFlake.nextIdStr();
            expenseOrder.setId(id);
            expenseOrder.setCreateTime(currentTime);
            expenseOrder.setCreateUser(userId);
            expenseOrderList.add(expenseOrder);
        }
        if (!expenseOrderList.isEmpty()) {
            assetsExpenseDao.insertBatch(expenseOrderList);
        }

        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() :
                ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setFailedList(failedList);
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(dataList.size() - failedList.size());
        resp.setFailedTotal(failedList.size());
        resp.setRetMessage(failedList.size() > 0 ? "导入固资预算信息部分成功" : "导入固资预算信息成功");
        return resp;
    }

    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private ExpenseOrder covertToBean(String[] record) {
        ExpenseOrder expenseOrder = new ExpenseOrder();
        expenseOrder.setAccountBook(record[0].trim());
        expenseOrder.setYear(record[1].trim());
        expenseOrder.setMonth(record[2].trim());
        expenseOrder.setDesc(record[3].trim());
        return expenseOrder;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[0].trim())) {
            addRowError("账套不能为空", rowErrors);
        } else {
            if (record[0].trim().length() > 20) {
                addRowError("账套长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("年度不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 4) {
                addRowError("年度长度不能超过4", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("月份不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 2) {
                addRowError("月份长度不能超过2", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("科目号不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 20) {
                addRowError("科目号字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[6].trim())) {
            addRowError("部门编码不能为空", rowErrors);
        } else {
            if (record[6].trim().length() > 20) {
                addRowError("部门编码长度不能超过20", rowErrors);
            }
        }
        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 补全数据
     *
     * @param originalList 原始数据
     * @param startNum     数据起始值
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<ExpenseOrder> originalList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        Map<String,Map<String,String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        int sort = startNum + 1;
        for (ExpenseOrder expenseOrder : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(expenseOrder);
            item.put("sort", sort);
            item.put("departmentName", departmentMap.containsKey(expenseOrder.getDepartment()) ? departmentMap.get(expenseOrder.getDepartment()).get("name") : "");
            resultList.add(item);
            sort++;
        }
        return resultList;
    }

}
